home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xarchie-2.0.9 / fchooser.c < prev    next >
C/C++ Source or Header  |  1995-06-18  |  9KB  |  280 lines

  1. /*
  2.  * fchooser.c : Xarchie interface to the FileChooser
  3.  *
  4.  * The FileChooser enforces very little policy. This wrapper adds
  5.  * the following:
  6.  * - The FileChooser is created with several other widgets: a Text
  7.  *   widget, and OK button, and a cancel button. These are created in
  8.  *   the sameparent, but other widgets can also be there.
  9.  * - Selecting a file in the FileChooser just puts the string in the
  10.  *   Text widget. You have to hit Ok to use it.
  11.  * - When ok is clicked or Return typed, the directory from the fileChooser
  12.  *   and the file from the Text are concatenated. If the result is a
  13.  *   directory, the fileChooser is reset to that directory. Otherwise
  14.  *   the callback is called with the filename as call_data.
  15.  * - Leading tildes are expanded in directories entered in the Text widget.
  16.  *
  17.  * Oh yeah, if FILECHOOSER is not defined, ignore all that about it. In that
  18.  * case we just have a Text and two buttons.
  19.  *
  20.  * George Ferguson, ferguson@cs.rochester.edu, 23 Apr 1993.
  21.  * 13 May 1993: Fixes for when FILECHOOSER not defined.
  22.  * 14 May 1993: More of the same (find MAXPATHLEN), initialize dir.
  23.  * 30 Jun 1993: Encore umax fixes from Gerry.Tomlinson@newcastle.ac.uk.
  24.  *
  25.  */
  26. #include "config.h"
  27. #ifdef HAVE_SYS_PARAM_H
  28. # include <sys/param.h>
  29. #endif
  30.  
  31. #include <stdio.h>
  32. #include <sys/types.h>
  33. #include <sys/stat.h>
  34. #ifndef S_ISDIR
  35. # define S_ISDIR(m) (m & S_IFDIR)    /* Encore umax */
  36. #endif
  37. #include <X11/Intrinsic.h>
  38. #include <X11/StringDefs.h>
  39. #include <X11/keysym.h>
  40. #include <X11/Xaw/Form.h>
  41. #include <X11/Xaw/Label.h>
  42. #include <X11/Xaw/AsciiText.h>
  43. #include <X11/Xaw/Command.h>
  44. #ifdef FILECHOOSER
  45. #include <FChooser.h>
  46. #endif
  47. #include "fchooser.h"
  48. #include "xarchie.h"
  49. #include "xutil.h"
  50. #include "tilde.h"
  51. #include "status.h"
  52. #include "alert.h"
  53. #include "debug.h"
  54.  
  55. /*
  56.  * Functions defined here:
  57.  */
  58. FileChooserInfo *createFileChooser(
  59. #if NeedFunctionPrototypes
  60.     Widget shell,
  61.     Widget parent,
  62.     char *basename,
  63.     FileChooserOkProc okCallback,
  64.     FileChooserCancelProc cancelCallback,
  65.     XtPointer client_data
  66. #endif
  67. );
  68.  
  69. #ifdef FILECHOOSER
  70. static void fileChooserCallback();
  71. #endif
  72. static void okButtonCallback(),cancelButtonCallback();
  73. static void keyPressEventHandler(),nonmaskableEventHandler();
  74.  
  75. /*    -    -    -    -    -    -    -    -    */
  76.  
  77. FileChooserInfo *
  78. createFileChooser(shell,parent,basename,okCallback,cancelCallback,client_data)
  79. Widget shell,parent;
  80. char *basename;
  81. FileChooserOkProc okCallback;
  82. FileChooserCancelProc cancelCallback;
  83. XtPointer client_data;
  84. {
  85.     FileChooserInfo *info;
  86.     char name[64];
  87.     Arg args[1];
  88.  
  89.     info = XtNew(FileChooserInfo);
  90.     info->shell = shell;
  91.     info->okCallback = okCallback;
  92.     info->cancelCallback = cancelCallback;
  93.     info->client_data = client_data;
  94. #ifdef FILECHOOSER
  95.     status0("Initializing File Selector...");
  96.     sprintf(name,"%sFileChooser",basename);
  97.     info->fcw =
  98.     XtCreateManagedWidget(name,xfwfFileChooserWidgetClass,parent,NULL,0);
  99.     XtAddCallback(info->fcw,XtNcallback,fileChooserCallback,(XtPointer)info);
  100.     status0("Done.");
  101.     XtSetArg(args[0],XtNfromVert,info->fcw);
  102. #else
  103.     XtSetArg(args[0],XtNfromVert,NULL);
  104. #endif
  105.     sprintf(name,"%sTextLabel",basename);
  106.     (void)XtCreateManagedWidget(name,labelWidgetClass,parent,args,1);
  107.     sprintf(name,"%sText",basename);
  108.     info->text =
  109.     XtCreateManagedWidget(name,asciiTextWidgetClass,parent,args,1);
  110.     sprintf(name,"%sOkButton",basename);
  111.     info->okButton =
  112.     XtCreateManagedWidget(name,commandWidgetClass,parent,NULL,0);
  113.     XtAddCallback(info->okButton,XtNcallback,okButtonCallback,(XtPointer)info);
  114.     /* Allow Return in the Text to be Ok */
  115.     XtAddEventHandler(info->text,KeyPressMask,False,
  116.               keyPressEventHandler,(XtPointer)info);
  117.     sprintf(name,"%sCancelButton",basename);
  118.     info->cancelButton =
  119.     XtCreateManagedWidget(name,commandWidgetClass,parent,NULL,0);
  120.     XtAddCallback(info->cancelButton,XtNcallback,
  121.           cancelButtonCallback,(XtPointer)info);
  122.     /* Allow WM_DELETE_WINDOW to the Shell to be Cancel */
  123.     if (info->shell != NULL)
  124.     XtAddEventHandler(info->shell,NoEventMask,True,
  125.               nonmaskableEventHandler,(XtPointer)info);
  126.     return(info);
  127. }
  128.  
  129. #ifdef FILECHOOSER
  130. /*
  131.  * When a selection is made, put the string in the Text item. If background
  132.  * selected, clear the Text item.
  133.  */
  134. /*ARGSUSED*/
  135. static void
  136. fileChooserCallback(w,client_data,call_data)
  137. Widget w;
  138. XtPointer client_data;    /* info */
  139. XtPointer call_data;    /* return struct */
  140. {
  141.     FileChooserInfo *fcinfo = (FileChooserInfo *)client_data;
  142.     XfwfFileChooserReturnStruct *ret =
  143.     (XfwfFileChooserReturnStruct *)call_data;
  144.     Arg args[1];
  145.  
  146.     DEBUG1("fileChooserCallback: fcinfo=0x%lx\n",fcinfo);
  147.     if (fcinfo == NULL || fcinfo->text == NULL)        /* creating */
  148.     return;
  149.     if (ret->file == NULL) {
  150.     XtSetArg(args[0],XtNstring,"");
  151.     } else {
  152.     XtSetArg(args[0],XtNstring,ret->file);
  153.     }
  154.     XtSetValues(fcinfo->text,args,1);
  155.     DEBUG0("fileChooserCallback: done\n");
  156. }
  157. #endif /* FILECHOOSER */
  158.  
  159. /*
  160.  * If Ok is clicked, get the directory from the FileChooser (if FILECHOOSER)
  161.  * and get the filename from the Text. Do tilde expansion. If result is
  162.  * a directory, use it in the FileChooser, otherwise invoke the callback
  163.  * passing filename and client_data. Finally free the info.
  164.  */
  165. /*ARGSUSED*/
  166. static void
  167. okButtonCallback(w,client_data,call_data)
  168. Widget w;
  169. XtPointer client_data;    /* info */
  170. XtPointer call_data;    /* not used */
  171. {
  172.     FileChooserInfo *fcinfo = (FileChooserInfo *)client_data;
  173.     static char filename[MAXPATHLEN];
  174.     struct stat statbuf;
  175.     char *dir,*file;
  176.  
  177.     DEBUG1("okButtonCallback: fcinfo=0x%lx\n",fcinfo);
  178.     filename[0] = '\0';
  179. #ifdef FILECHOOSER
  180.     dir = XfwfFileChooserCurrentDirectory((XfwfFileChooserWidget)(fcinfo->fcw));
  181.     DEBUG1("okButtonCallback: dir=\"%s\"\n",dir);
  182. #else
  183.     dir = "";
  184. #endif
  185.     file = getWidgetString(fcinfo->text);
  186.     if (file == NULL || *file == '\0') {
  187.     alert0("No filename specified!");
  188.     return;
  189.     }
  190.     DEBUG1("okButtonCallback: file=\"%s\"\n",file);
  191.     if (*file == '/') {                    /* absolute path */
  192.     strcpy(filename,file);
  193.     } else if (*file == '~') {                /* tilde path */
  194.     strcpy(filename,tildeExpand(file));
  195.     } else {                        /* relative to fcw */
  196.     sprintf(filename,"%s%s",dir,file);
  197.     }
  198.     DEBUG1("okButtonCallback: filename=\"%s\"\n",filename);
  199. #ifdef FILECHOOSER
  200.     /* If we got a directory, go open it rather than use it */
  201.     if (stat(filename,&statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
  202.     XfwfFileChooserChangeDirectory((XfwfFileChooserWidget)fcinfo->fcw,
  203.                        filename);
  204.     return;
  205.     }
  206. #endif    
  207.     if (fcinfo->okCallback != NULL) {
  208.     DEBUG0("okButtonCallback: calling okCallback...\n");
  209.     (*(fcinfo->okCallback))(fcinfo,filename,fcinfo->client_data);
  210.     }
  211.     DEBUG0("okButtonCallback: done\n");
  212. }
  213.  
  214. /*
  215.  * If Cancel is clicked, invoke the callback passing client_data.
  216.  * Finally free the info.
  217.  */
  218. /*ARGSUSED*/
  219. static void
  220. cancelButtonCallback(w,client_data,call_data)
  221. Widget w;
  222. XtPointer client_data;    /* fcinfo */
  223. XtPointer call_data;    /* not used */
  224. {
  225.     FileChooserInfo *fcinfo = (FileChooserInfo *)client_data;
  226.  
  227.     DEBUG1("cancelButtonCallback: fcinfo=0x%lx\n",fcinfo);
  228.     if (fcinfo->cancelCallback != NULL) {
  229.     DEBUG0("cancelButtonCallback: calling cancelCallback\n");
  230.     (*(fcinfo->cancelCallback))(fcinfo,fcinfo->client_data);
  231.     }
  232.     DEBUG0("cancelButtonCallback: done\n");
  233. }
  234.  
  235. /*
  236.  * KeyPress event handler for Text item: When Return is typed, act as if
  237.  * OK had been clicked. If this event isn't Return, just let it be
  238.  * dispatched normally.
  239.  */
  240. /*ARGSUSED*/
  241. static void
  242. keyPressEventHandler(w,client_data,event,continue_to_dispatch)
  243. Widget w;
  244. XtPointer client_data;
  245. XEvent *event;
  246. Boolean *continue_to_dispatch;
  247. {
  248.     KeySym keysym;
  249.     char str[8];
  250.  
  251.     DEBUG1("keyPressHandler: w=0x%x\n",w);
  252.     (void)XLookupString((XKeyEvent*)event,str,sizeof(str),&keysym,NULL);
  253.     if (keysym == XK_Return) {
  254.     DEBUG0("keyPressHandler: calling okButtonCallback...\n");
  255.     okButtonCallback(NULL,client_data,NULL);
  256.     }
  257.     DEBUG0("keyPressHandler: done\n");
  258. }
  259.  
  260. /*
  261.  * Nonmaskable event handler for Shell: If the event is a ClientMessage
  262.  * of WM_PROTOCOLS then act as if Cancel had been clicked.
  263.  */
  264. /*ARGSUSED*/
  265. static void
  266. nonmaskableEventHandler(w,client_data,event,continue_to_dispatch)
  267. Widget w;
  268. XtPointer client_data;
  269. XEvent *event;
  270. Boolean *continue_to_dispatch;
  271. {
  272.     DEBUG1("nonmaskableHandler: w=0x%x\n",w);
  273.     if (event->type == ClientMessage &&
  274.         event->xclient.data.l[0] == WM_DELETE_WINDOW) {
  275.     DEBUG0("nonmaskableHandler: calling cancelButtonCallback\n");
  276.     cancelButtonCallback(NULL,client_data,NULL);
  277.     }
  278.     DEBUG0("nonmaskableHandler: done\n");
  279. }
  280.